package com.hy.greedy;

import java.util.Arrays;

public class SumOfMaxSubsequence {


    /**
     * 53. 最大子序和
     * 力扣题目链接
     *
     * 给定一个整数数组 nums ，找到一个具有最大和的连续子数组（子数组最少包含一个元素），返回其最大和。
     *
     * 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4] 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大，为 6。
     *
     * 贪心解法
     * 贪心贪的是哪里呢？
     *
     * 如果 -2 1 在一起，计算起点的时候，一定是从1开始计算，因为负数只会拉低总和，这就是贪心贪的地方！
     *
     * 局部最优：当前“连续和”为负数的时候立刻放弃，从下一个元素重新计算“连续和”，因为负数加上下一个元素 “连续和”只会越来越小。
     *
     * 全局最优：选取最大“连续和”
     *
     *  "局部最优的情况下，并记录最大的“连续和”，可以推出全局最优。"
     *
     * 从代码角度上来讲：遍历nums，从头开始用count累积，如果count一旦加上nums[i]变为负数，那么就应该从nums[i+1]开始从0累积count了，因为已经变为负数的count，只会拖累总和。
     *
     * 这相当于是暴力解法中的不断调整最大子序和区间的起始位置。
     *
     * 那有同学问了，区间终止位置不用调整么？ 如何才能得到最大“连续和”呢？
     * @param num
     * @return
     */

    // 贪心算法
    public int sumOfMaxSubSeq(int [] num){
        if (num.length == 1){
            return num[0];
        }
        int sum = 0;
        int count = 0;
        for (int i = 0; i < num.length; i++) {
            count += num[i];
            // 取区间累计的最大值（相当于不断确定最大子序终止位置）
            sum = Math.max(count,sum);
            // 相当于重置最大子序起始位置，因为遇到负数一定是拉低总和
            if (count < 0){
                count = 0;
            }
        }
        return sum;
    }

    // DP  动态规划
    public int maxSubArray(int [] num){
        int sum = 0;
        int [] dp = new int[num.length];
        dp[0] = num[0];
        sum = dp[0];
        for (int i = 1; i < num.length; i++) {
            dp[i] = Math.max(dp[i-1] + num[i],num[i]);
            sum = Math.max(dp[i],sum);
        }
        return sum;
    }


    public static void main(String[] args) {
        int [] num = {-2,1,-3,4,-1,2,1,-5,4};
        SumOfMaxSubsequence subSeq = new SumOfMaxSubsequence();
        System.out.println("res: "+subSeq.sumOfMaxSubSeq(num));
        System.out.println("res: "+subSeq.maxSubArray(num));
    }
}
